package ru.stepanovdn.trading.server.service.candle

import jakarta.annotation.PostConstruct
import org.slf4j.LoggerFactory
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.context.annotation.DependsOn
import org.springframework.stereotype.Service
import org.springframework.util.CollectionUtils
import ru.stepanovdn.trading.server.service.processor.PurchaseService
import ru.stepanovdn.trading.server.service.tinkoff.ITinkoffCommonAPI
import ru.stepanovdn.trading.server.strategy.StrategySelector
import ru.tinkoff.piapi.contract.v1.HistoricCandle

/**
 * Service to observe candles
 */
@Service
@DependsOn("candleHistoryService")
@ConditionalOnProperty(name = ["candle.listener.enabled"], havingValue = "true")
class CandleListenerService {

    private val log = LoggerFactory.getLogger(javaClass)

    private val candleHistoryService: CandleHistoryService? = null
    private val purchaseService: PurchaseService? = null
    private val strategySelector: StrategySelector? = null
    private val tinkoffCommonAPI: ITinkoffCommonAPI? = null

    private fun startToListen() {
        val figies: Set<String> = strategySelector!!.figiesForActiveStrategies
        if (CollectionUtils.isEmpty(figies)) {
            log.warn("No figies to subscribe")
            return
        }

        log.info("Start to listen candle events..")
        try {
            tinkoffCommonAPI!!.api!!.marketDataStreamService
                .newStream("candles_stream", { item ->
                    log.trace("New data in streaming api: {}", item)
                    if (item.hasCandle()) {
                        val historyCandle: HistoricCandle.Builder = HistoricCandle.newBuilder()
                        historyCandle.setClose(item.candle.close)
                        historyCandle.setOpen(item.candle.open)
                        historyCandle.setHigh(item.candle.high)
                        historyCandle.setLow(item.candle.low)
                        historyCandle.setTime(item.candle.time)
                        val candle =
                            candleHistoryService!!.addOrReplaceCandles(historyCandle.build(), item.candle.figi)
                        purchaseService!!.observeCandleNoThrow(candle)
                    }
                }, { e ->
                    log.error("An error in candles_stream, listener will be restarted", e)
                    startToListen()
                })
                .subscribeCandles(figies.toMutableList())
        } catch (th: Throwable) {
            log.error("An error in subscriber, listener will be restarted", th)
            startToListen()
            throw th
        }
    }

    @PostConstruct
    fun init() {
        Thread({ this.startToListen() }, "event-listener").start()
    }
}
